//
//  DJIConnectManager.m
//  DJILogin
//
//  Created by wenpd on 2021/3/31.
//

#import "DJIConnectManager.h"
#import <QBUtility/ZQLog.h>
#import <SVProgressHUD/SVProgressHUD.h>

@interface DJIConnectManager() <DJISDKManagerDelegate,
DJIFlightControllerDelegate,
DJIRTKDelegate,
DJIOnboardSDKDeviceDelegate,
DJICameraDelegate,
DJIGimbalDelegate,
DJIBatteryDelegate,
DJIBatteryAggregationDelegate>

@end

@implementation DJIConnectManager

#pragma mark 初始化
- (instancetype)init {
    self = [super init];
    if (self) {
        
        [self customInitProperty];
        [self customInitAction];
        
    }
    return self;
}

- (void)customInitProperty {
    //初始化
    _isDroneConnect = NO;
    _cameraMode = DJICameraModeShootPhoto;
    
    //信号
    _aircraftSingal = [RACSubject subject];
    _fcStateSingal = [RACSubject subject];
    _imuStateSingal = [RACSubject subject];
    _onBoardSingal = [RACSubject subject];
    _rtkStateSingal = [RACSubject subject];
    _rtkStationSingal = [RACSubject subject];
    _cameraStateSingal = [RACSubject subject];
    _sdcardStateSingal = [RACSubject subject];
    _mediaSingal = [RACSubject subject];
    _gimbalStateSingal = [RACSubject subject];
    _batteryStateSingal = [RACSubject subject];
}

- (void)customInitAction {
    [self registerSDK];
}


- (void)registerSDK {
    [DJISDKManager registerAppWithDelegate:self];
}

- (void)loginDJISDK:(BOOL)isInChina {
    [[DJISDKManager userAccountManager] logIntoDJIUserAccountWithAuthorizationRequired:isInChina withCompletion:^(DJIUserAccountState state, NSError * _Nullable error) {
        if (error) {
            [SVProgressHUD showErrorWithStatus:[NSString stringWithFormat:@"登录失败，%@", error.description]];
        }
    }];
}


- (void)appRegisteredWithError:(NSError * _Nullable)error {
    if (error) {
        
        NSString *message = [NSString stringWithFormat:@"SDK注册失败, 请联网重试！失败原因：%@", error.description];
        //注册失败
        [SVProgressHUD showWithStatus:message];
        
        //日志记录
        [ZQLog bLogI:message];
    }
    else {
        //日志记录
        [ZQLog bLogI:@"SDK注册成功，准备连接无人机"];
#if ENABLE_DEBUG_MODE
        [DJISDKManager enableBridgeModeWithBridgeAppIP:@"192.168.31.93"];
#else
        //开始准备连接飞机
        [DJISDKManager startConnectionToProduct];
        [[DJISDKManager userAccountManager] logIntoDJIUserAccountWithAuthorizationRequired:NO withCompletion:nil];
#endif
    }
}

- (void)productConnected:(DJIBaseProduct *)product {
    //无人机已连接
    if ([product isKindOfClass:[DJIAircraft class]]) {
        
        [ZQLog bLogI:[NSString stringWithFormat:@"无人机已连接, model:%@", product.model]];
        
        self.aircraft = (DJIAircraft *)product;
        self.isDroneConnect = YES;
        self.isM300RTK = [product.model isEqual:DJIAircraftModelNameMatrice300RTK];
        [self.aircraftSingal sendNext:product];
        
        [self settingDelegate];
    }
    else if ([product isKindOfClass:[DJIHandheld class]]) {
        //手持设备
        [SVProgressHUD showSuccessWithStatus:@"已检测到手持设备"];
        
        //日志
        [ZQLog bLogI:[NSString stringWithFormat:@"手持设备已连接, model:%@", product.model]];
    }
}

- (void)productDisconnected {
    
    //日志
    [ZQLog bLogI:@"设备断开连接"];
    
    //无人机断开连接
    self.aircraft = nil;
    self.isDroneConnect = NO;
    [self.aircraftSingal sendNext:nil];
}


#pragma mark 设置代理
- (void)settingDelegate {
    
    @weakify(self);
    [[[RACObserve(self.aircraft, flightController) ignore:nil] take:1] subscribeNext:^(DJIFlightController *fc) {
        @strongify(self);
        fc.delegate = self;
        
        //日志
        [ZQLog bLogI:@"设置飞控代理"];
        
        [[[RACObserve(fc, onboardSDKDevice) ignore:nil] take:1] subscribeNext:^(DJIOnboardSDKDevice *ob) {
            ob.delegate = self;
            
            //日志
            [ZQLog bLogI:@"设置onboardSDKDevice代理"];
        }];
        
        [[[RACObserve(fc, RTK) ignore:nil] take:1] subscribeNext:^(DJIRTK *rtk) {
            rtk.delegate = self;
            
            //日志
            [ZQLog bLogI:@"设置RTK代理"];
        }];
    }];
    
    [[[RACObserve(self.aircraft, camera) ignore:nil] take:1] subscribeNext:^(DJICamera *camera) {
        @strongify(self);
        camera.delegate = self;
        
        //日志
        [ZQLog bLogI:@"设置camera代理"];
    }];
    
    [[[RACObserve(self.aircraft, gimbal) ignore:nil] take:1] subscribeNext:^(DJIGimbal *gimbal) {
        @strongify(self);
        gimbal.delegate = self;
        
        //日志
        [ZQLog bLogI:@"设置gimbal代理"];
    }];
    
    //For M300RTK batteries is always null
    if(!self.aircraft.batteries){
        DJIBattery.aggregationDelegate = self;
    } else {
        [[[RACObserve(self.aircraft, batteries) ignore:nil] take:1] subscribeNext:^(NSArray *batteries) {
            @strongify(self);
            
            NSInteger count = batteries.count;
            for (int i = 0; i < count; i ++) {
                DJIBattery *battery = batteries[i];
                battery.delegate = self;
            }
            //日志
            [ZQLog bLogI:[NSString stringWithFormat:@"设置battery代理, battery数量:%@", @(count)]];
        }];
    }
    //set Camera source for M300
    if(self.isM300RTK){
        [self assignSourceForM300:YES];
    }
}

#pragma mark 将云台相机设置为主相机，云台相机可能是LEFTCAM/RIGHTCAM
- (void)assignSourceForM300:(BOOL)isLeft{
    @weakify(self);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{
        DJIAirLink* airLink = ((DJIAircraft*)[DJISDKManager product]).airLink;
        DJIVideoFeedPhysicalSource primarySource = isLeft?DJIVideoFeedPhysicalSourceLeftCamera:DJIVideoFeedPhysicalSourceRightCamera;
        [airLink.ocuSyncLink assignSourceToPrimaryChannel:primarySource secondaryChannel:DJIVideoFeedPhysicalSourceFPVCamera withCompletion:^(NSError * _Nullable error) {
            @strongify(self);
            if(error){
                [ZQLog bLogI:[NSString stringWithFormat:@"set source erorr:%@", error.localizedDescription]];
                if(isLeft){
                    [self assignSourceForM300:NO];
                }
            } else {
                [ZQLog bLogI:@"set source success"];
            }
        }];
    });
}

#pragma mark 飞控的代理
- (void)flightController:(DJIFlightController *_Nonnull)fc didUpdateState:(DJIFlightControllerState *_Nonnull)state {
    //飞控状态
    [_fcStateSingal sendNext:state];
}

- (void)flightController:(DJIFlightController *_Nonnull)fc didUpdateIMUState:(DJIIMUState *_Nonnull)imuState {
    //IMU状态
    [_imuStateSingal sendNext:imuState];
}

#pragma mark 板子的代理
- (void)onboardSDKDevice:(DJIOnboardSDKDevice *)osdkDevice
     didSendDataToMobile:(NSData *)data {
    
    [ZQLog bLogI:[NSString stringWithFormat:@"收到板子消息"]];
    
    //板子发来了数据
    [_onBoardSingal sendNext:data];
}

#pragma mark rtk
- (void)rtk:(DJIRTK *_Nonnull)rtk didUpdateState:(DJIRTKState *_Nonnull)state {
    //RTK状态
    [_rtkStateSingal sendNext:state];
}

- (void)rtk:(DJIRTK *_Nonnull)rtk didUpdateBaseStationsList:(NSArray <DJIRTKBaseStationInformation *> *)informations{
    [_rtkStationSingal sendNext:informations];
}

#pragma mark 相机的代理
- (void)camera:(DJICamera *_Nonnull)camera didUpdateSystemState:(DJICameraSystemState *_Nonnull)systemState {
    //相机的模式，相机是否有异常
    if (systemState.mode != _cameraMode && (!camera.isFlatCameraModeSupported)) {
        [camera setMode:_cameraMode withCompletion:nil];
    }
    [_cameraStateSingal sendNext:systemState];
}

- (void)camera:(DJICamera *_Nonnull)camera didGenerateNewMediaFile:(DJIMediaFile *_Nonnull)newMedia {
    //捕获一张照片
    [_mediaSingal sendNext:newMedia];
}

- (void)camera:(DJICamera *_Nonnull)camera didUpdateStorageState:(DJICameraStorageState *_Nonnull)storageState {
    //存储空间
    [_sdcardStateSingal sendNext:storageState];
}

#pragma mark gimbal
- (void)gimbal:(DJIGimbal *)gimbal didUpdateState:(DJIGimbalState *)state {
    //云台状态
    [_gimbalStateSingal sendNext:state];
}

#pragma mark battery
- (void)battery:(DJIBattery *_Nonnull)battery didUpdateState:(DJIBatteryState *_Nonnull)state {
    
    //在状态中记录电池的index
    if (_aircraft.batteries.count > 1) {
        [state setValue:@(battery.index) forKey:@"numberOfDischarges"];
    }
    
    //更新电池状态
    [_batteryStateSingal sendNext:state];
}

#pragma  mark battery for M300 RTK
- (void)batteriesDidUpdateState:(DJIBatteryAggregationState *_Nonnull)state{
    //更新电池状态
    [_batteryStateSingal sendNext:state];
}
@end
